A list of the basic, and most interactive, commands are presented along with an example of their use. These are the minimum commands necessary to use the program:
draw
Draw a fractal based on the current maps. Press a key to stop.
E.g. green color fern draw
cdraw
Plots each map in a different color.
E.g. spiral cdraw
<n> edit
Edit the n-th map. Enter a new value or press return to leave the
existing value as is.
E.g. 2 edit
a = 0.5 ?-0.5 (new value)
b = -0.5 ?<return> etc.
zero-maps
Erase all twelve maps.
E.g. zero-maps
<color.name> color
Set the current drawing color to the color named. Valid colors are
Set the origin to (x,y). X and Y are floating point numbers.
E.g. -0.354 .789 origin
<u> <v> screen
Set the screen origin to (u,v) (pixels).
E.g. 120 220 screen
<r> range
Set the range to <r> (floating point). The viewing window is a
square with the lower left corner as the origin and side length
as range.
E.g. 0.5 range
<x> <y> scale
Set the x-axis and y-axis scales to the floating point values given.
The default scale is 1.0 for a full screen image. Changing the scale
to a value less than one shrinks the image, greater than one expands
the image.
E.g. 2.0 2.0 scale
mouse
When issued, mouse will translate the position of the pointer into
an x,y coordinate allowing the user to 'see' where certain parts of
the image are. Clicking the mouse button will select that point as
the new origin and decrease the range by a factor of two.
on|off axes
Turn the coordinate axes (really a mark on the origin) ON or OFF.
E.g. off axes
on|off outlines
Set showing the map outlines on or off, press a key to continue
after viewing the outlines.
E.g. on outlines
settings
Show a list of the current origin, screen origin, range, scale, number
of maps and whether the axes and outlines are on or off.
E.g. settings
findmap
Allows the user to enter three initial coordinates and three image
coordinates and calculates the map for those values.
E.g. findmap
make
Puts the most recent values from findmap on the stack in order
for set. The user needs to add the probability and map number
before calling set.
E.g. make .333 1 set
<a> <b> <c> <d> <e> <f> <p> <n> set
Sets the parameters for a map. The letters a-f correspond to the
values for the matrix and offset vector, <p> is the probability for
the map and <n> is the map number. All values except <n> are to
be floating point numbers.
E.g. 0.5 -0.5 0.5 0.5 0.0 0.0 0.5 1 set
<m1> <m2> copy
Copy map number <m1> to <m2> without disturbing <m1>.
E.g. 2 5 copy
<m> delete
Delete map number <m> and move any other maps up in memory.
E.g. 3 delete
<m> insert
Insert a blank map before map <m>.
E.g. 1 insert
cls
Clear the window.
E.g. cls
bye
Exit Fractal Lab Kit.
E.g. bye
••Using the FindMap command
_FindMap_ allows the user to find the parameters for a map by entering the coordinates and where they map to. This example will use the FindMap command to calculate the maps for the Mandelbrot Dragon.
With the program running enter 'findmap'. You will see be asked to enter the coordinates of three points from the original map. The origin, the lower right and upper left corners of the initial box (remember, it goes from 0..1 in both x and y) make good starting places. Therefore, enter 0 for x1 and 0 for y1, (1,0) for (x2,y2), and (0,1) for (x3,y3). These are the default values. You do not need to enter a decimal point with each number in this case, pressing return uses the value displayed. For the image points, enter (x1',y1') as (0,0), (x2',y2') as (0.5,0.5) and (x3',y3') as (-0.5,0.5). The program will calculate the appropriate map and display its values. At the prompt, enter
make 0.5 1 set
to make this newly calculated map the first map. Enter 'findmap' again and press return for each of the original points since we will use the same ones as before. For the image points enter (x1',y1') as (1,0), (x2',y2') as (0.5,0.5) and (x3',y3') as (0.5,-0.5). Then enter,
make 0.5 2 set
to fix this as the second map. Lastly, enter,
2 maps 120 220 screen cdraw
to use two maps, adjust the screen origin so the image will fit, and draw using color.
••Writing your own fractals to disk
Unfortunately, Fractal Lab Kit is unable to write fractal maps to disk. Therefore, when you use {\tt FindMap} to create a new map you must write it down by hand. When you are finished designing a new fractal you can use any text editor, like TeachText, to create a file to load the map from disk. Simply enter the skeleton code on the next few lines, substituting your values for the letters indicated. See the structure of the included fractals as an example.
: myfractal ( give it a name, remember, comments in parentheses )
a b c d e f p 1 set ( enter the values for map 1 )
a' b' c' d' e' f' p' 2 set ( enter the values for map 2, etc. )
n maps ; ( `n' is the number of maps you are entering )
Once loaded from disk, you need to enter the name of the fractal to load the maps and you are ready to draw.
•Advanced Features
••A very (very) brief introduction to programming in Forth
Forth is an interpreted, stack based programming language known for its speed and extensibility. This is not an attempt to completely teach Forth so much as to teach a little about Forth so that the user who is unfamiliar with Forth can make some use of the language.
Forth is a stack based language, data is manipulated using a stack that works in a way very similar to the lunch trays in a cafeteria. The last tray in the stack is the first one out. Because of this, all mathematical operations are in postfix format, i.e., instead of typing 4 + 7 one would type 4 7 + which would leave the value 11 on the top of the stack. This illustrates an important thing to remember about using Forth, anything that is entered is interpreted as either a word in the dictionary (more on that later) or a number to be pushed on the stack, so entering 4 7 + told Forth to push a 4 on the stack followed by a 7 and the + word adds the top two stack items. To see the value stored on the top of the stack use the . word. Note that this is a destructive operation, it prints the value at the top of the stack and removes it from the stack as well. To see the top stack value but not remove it you need to enter dup . to first duplicate the top item and then print it. By default, Forth only operates on 16-bit integers but Pocket Forth supports real numbers as well. Forth will interpret a value as a real number only if it contains a decimal point! It is therefore important to enter a decimal point for every number that should be a real number and to not use one on numbers that should be integers.
Forth supports the standard arithmetic operations: +, -, *, / (integers) and f+, f-, f*, f/ (real numbers). Use f. to print the top of stack as a real number. fdup duplicates the real number at the top of the stack while fswap will switch the top two real numbers on the stack. These few words will allow for using Forth as a simple calculator. Forth, typically, does not support higher mathematical functions, though Pocket Forth does.
Forth derives its extensibility from the way in which programs are written. As Forth interprets tokens from the input line (anything surrounded by spaces is a token) it either pushes it on the stack as a number or looks it up as a word in its dictionary. A Forth program, therefore, consists of adding definitions to the dictionary. Definitions are begin with the : word and end with a ; word. Once defined, the word can be used in subsequent definitions. Parameters are passed via the stack. Forth does allow for the use of variables and constants, though these are slower than the stack. Use the word variable (or fvariable) followed by the name for the variable to create one. Use «value» constant ( or fconstant) «name» to define a constant.
Examples: typing 'fvariable stddev' (no quotes) will create room in the dictionary for a floating point variable named stddev while typing 3.141592 fconstant PI will create a constant for pi. Forth is case-insensitive. Constants are really special words that push the value on the stack so that typing pi will cause the value to be pushed on the stack. However, entering the name of a variable will NOT place its value on the stack, but rather, the address where the variable is stored will be placed on the stack. To get the value of a variable a two word combination must be used: stddev f@ will `fetch' the floating point number stored at the address that stddev places on the stack. Similarly, the value of an integer variable is found using @ instead of f@. To store a value in a variable, use ! or f!, 3 age ! or 1.414 sqr2 f!.
Forth uses several standard control structures: «if else then», «do loop or +loop», «begin until», «begin while repeat», and «begin again». The phrase
count @ 100 < if ." Yes, there is room" cr
else ." No, there is no room." cr then
will check whether the current value of count is less than 100 or not. Forth supports <, >, and = for comparing integer values. Pocket Forth has a
single word for comparing floating point numbers, fcompare, which returns
a -1 if f1<f2, 0 if f1=f2, and +1 if f1>f2, where f1 and f2 are the top two stack numbers (assumed to be floating point). It is important to note that unlike most other Forth words, fcompare does _not_ remove the top two
floating point numbers. The do loop is similar to the for loops in other languages. As might be expected, the syntax is
«hi» «lo» do «body» loop
where the index (pushed on the stack by the word r) will go from lo to hi-1. A variation is to use +loop instead of loop to jump by the value on the top of the stack (which must be positive). «Begin until» and «begin while repeat»
are for bottom tested and top tested conditional loops. The condition is the same as the if statement:
0 begin ." Hello" cr 1+ dup 99 > until
will print the word `Hello' 100 times. Similarly, this fragment will also
print `Hello' 100 times:
0 begin dup 100 < while ." Hello" cr 1+ repeat
••Putting it all together
The following examples will illustrate the creation of simple Forth words.
1. Averaging four numbers:
: ave4 ( a b c d -- average ) + + + 4 / ;
Using integer arithmetic, sum the top four stack items and divide the result by 4. Illustrates comments which are anything surrounded by `()', note the space after the `('. The comment given is known as a _stack effect comment_ and shows the word's effect on the stack. Initial stack items are on the left of the `--' and the result is on the right.
2. Averaging N floating point numbers
: averageN ( a1. ... aN. N -- average. )
dup >r ( save N on the return stack )
1- 0 do f+ loop ( adjust N and add the values )
r> ( get N off the return stack )
0 d>f f/ ; ( make it real and divide to find average )
This example illustrates use of the return stack. The return stack is the place where Forth places addresses to return to when the current word is done executing. While a word is executing it is possible to use the return stack for temporary storage, but one must be careful to make sure that all values placed on the stack by >r are removed using r> before the word is done, otherwise Forth will attempt to return to who knows where and will very
likely crash. Integers are transformed into real numbers by the two word sequence 0 d>f. This transforms the integer into a double length integer and then into a real number.
3. Evaluating a function: y = 3.4e^x:
fvariable x
: sqr ( x. -- x.*x. ) fdup f* ;
: cube ( x. -- x.^3 ) fdup fdup f* f* ;
: expf ( x. -- exp[x.] ) ( use Taylor series approx. )
fdup x f! 1.0 f+ x f@ sqr 2.0 f/ f+ x f@ cube 6.0 f/ f+ ;
: Y ( x. -- Y[x.] ) expf 3.4 f* ; ( keep x < 1 for accuracy )
This is an example of factoring. The code for the square and cube could easily have been left in the definition of expf but factoring them out made the definition shorter and easier to read. In theory, according to some, a properly factored Forth program combined with well chosen word names and stack effect comments should be nearly self-documenting. By the way, Pocket Forth already has a word for calculating the exponential, expt. Compare expf with expt to see how large x can be before the error introduced by truncating the Taylor series at x^{3} becomes too great.
These examples are brief, but hopefully should be sufficient, especially when combined with a list of Forth words, to allow you to write simple words to extend the power of the program.
••The Sierpinski triangle, an example
The Sierpinski Triangle is a commonly seen fractal consisting of a triangle made of triangles. This will serve as an example of how the program can be extended by adding words to the Forth dictionary. The triangle is made up of three maps that divide the region 0..1 in x and 0..1 in y into three equal squares. We will develop a Forth word that will find the maps for the triangle and then generate the fractal.
First, we must determine the maps. The findmap command's interactive nature is unsuited to our task, fortunately, there are three `primitive' (i.e. non-interactive) words that will perform the same task: initial, image, and solve. These words operate as follows:
x1 y1 x2 y2 x3 y3 initial
«Sets the initial points for finding a map, (x1,y1),(x2,y2),(x3,y3)»
X1 Y1 X2 Y2 X3 Y3 image
«Sets the image points for finding a map, (X1,Y1),(X2,Y2),(X3,Y3)»
solve
«Finds the values that will map the initial points to the image points»
These words, when combined with 'make' and 'set', will allow us to create a single Forth word to find all three maps at once. At this point, then, we can write:
: sierpinski ( generates the Sierpinski Triangle)
( Set up initial values, for all maps )
0.0 0.0 1.0 0.0 0.0 1.0 initial
( First map )
0.0 0.0 0.5 0.0 0.0 0.5 image solve
make 0.333 1 set
( Second map )
0.5 0.0 1.0 0.0 0.5 0.5 image solve
make 0.333 2 set
( Third map )
0.25 0.5 0.75 0.5 0.25 1.0 image solve
make 0.333 3 set
Now before viewing the fractal show the maps, reset the program, show the settings, and draw the outlines:
( Show the maps )
page ." The Sierpinski maps: " cr showmaps
reset settings
key drop ( wait for a key press )
( Show outlines when drawing )
on outlines
( Reset the program and draw the fractal )
cdraw ;
Try this word and see what happens.
••Basic Forth words
The table lists some basic Forth words and their use. With these it should be possible to define your own words for use with the program.
+, -, *, / ( a b -- a$b ) Math, where $ is an operation
mod ( a b -- a mod b ) Remainder after dividing
drop ( a -- ) Drop the top stack item
cr ( -- ) Print a return character
space ( -- ) Print a space (ASCII 32)
emit ( a -- ) Print the character whose code is on the stack
." ( -- ) Print text until a " found (definitions only)
. ( a -- ) Print the top of stack
key ( -- a ) Get a key, ASCII code on stack
bye ( -- ) Exit from Forth
?terminal ( -- b ) Has a key been pressed?
( ( -- ) Start a comment (remember space)
!pen ( x y -- ) Move the pen to (x,y) (pixels)
-to ( x y -- ) Line from current to (x,y)
page ( -- ) Clear the screen
--> ( -- ) Load filename, no spaces!
open ( -- ) Load file chosen in Mac dialog
?button ( -- t ) Mouse button down?
@mouse ( -- x y ) Push mouse position on stack
save ( -- ) Save the current dictionary
See the reference section for more words that are program specific. The last eight words listed are special to Pocket Forth and may not be available on other Forth systems, though there will likely be something similar. Those interested in seriously learning Forth (some swear that it is the best computer language there is) should get a hold of the book _Starting Forth_ by Leo Brodie (2nd ed. 1987), it is an excellent and entertaining introduction.
•Using the Shell
Fractal Lab Kit contains a mouse driven shell. The shell is a single Forth
word (named shell) that allows you to use the mouse to set many of the parameters used in generating fractals. The shell makes it easy to change settings, colors, edit and calculate maps, and draw. The only thing the shell cannot do is load fractals from disk. The use of the shell is straightforward, simply click on the command you want to execute. Numerical data is entered at the bottom of the screen. When more than one item of information needs to be entered you must press the `return' key after each item. The application menu bar is disabled when the shell is running, use the Forth or Quit commands to exit the shell or program.
The shell uses much of the memory available to Forth. This might cause a problem if you are creating more sophisticated programs. You can eliminate the shell code by entering 'forget shellcode' when in interactive mode. This is exactly what the Cathedral demo program does. The code is erased from Forth's memory and will be permanently erased should the word save be entered after the code is cleared. Alternatively, one could select 'Save Dictionary' from the _File_ menu instead of using the word 'save'. This will write the current Forth dictionary into the application itself. This should never be a problem since everyone runs from backup copies only, right? This is also a way to create a version of Fractal Lab Kit that has more memory for your own programs.
If you are designing a new fractal the shell will be handy since it lets you change values quickly. Write your maps down though since Fractal Lab Kit has no ability to save maps to disk! If you are manipulating a fractal stored on disk you must load it in interactive mode (i.e. go to Forth), enter its name to load the maps, and then enter the shell. For example, the following lines in interactive mode will load the fern maps from disk and enter the shell to allow you to work with the fractal:
--> :maps:fern (load the maps from disk)
fern shell (load the maps & enter the shell)
Try switching the signs of the a and c values in the first fern map to change the fern into a weed. Use the Help command for a quick summary of the commands available in the shell. Note that the help screen in interactive mode is different than the one in shell mode.
•Reference
••Commands
draw
Draw a fractal based on the current maps. Press a key to stop.
E.g. green color fern draw
cdraw
Except for plotting each map in a different color, it is the same as
draw.
E.g. spiral cdraw
<n> idraw or <n> icdraw
Same as draw and cdraw respectively except for iterating through
<n>*500 points. Useful for drawing a fractal and stopping without
user interaction.
<n> edit
Edit the n-th map. Enter a new value or press return to leave the
existing value as is.
E.g. 2 edit
a = 0.5 ?-0.5 (new value)
b = -0.5 ?<return> etc.
zero-maps
Erase all twelve maps.
E.g. zero-maps
<color.name> color
Set the current drawing color to the color named. Valid colors are
Show individual settings. settings calls each of these.
<n> show
Show the values of map <n>.
E.g. 3 show
•Primitive commands
These commands (words) are `primitive' in the sense that they are called by the regular command words. As they are standard Forth words they are available to the user as well.
input ( -- a )
Get a 16-bit integer on the stack.
finput ( -- f b )
Get a floating point number on the stack and a boolean value that is
false if the user pressed the return key only, in which case the
number is 0.0.
#map->addr ( a -- addr )
Convert a number for a map into an address to the map location in
memory.
get ( offset map# -- value )
Get a value for a particular map. The offset is a branch into the
map, each value is 10 bytes long. The constants a,b,c,d,e,f and p
are defined to give the proper offset: c 3 get returns the c value
of the third map.
update ( value offset map# -- )
Put the value in the numbered map at the offset (use a-f or p).
print ( addr -- )
Print the map starting at addr.
wsize ( h v -- )
Resize the window to h pixels high and v pixels across.
dot ( u v -- )
Draw a dot on the screen at (u,v) (pixels).
plot ( x. y. -- )
Plot the point (x,y) on the screen.
plotto ( x. y. -- )
Draw a line from the last plotted point to (x,y).
determinant ( -- d )
Find the determinant of the 3x3 matrix whose values are stored
in the floating point variables d1 through d9. Values in the form:
[ [d1,d2,d3],[d4,d5,d6].[d7,d8,d9]].
x->d ( -- )
Copy the values in x1,y1 .. x3,y3 to the matrix d. Used to setup for
finding a map.
xy->uv ( x. y. -- u v )
Change real coordinates (x,y) into screen coordinates (u,v). Call
factor first.
factor ( -- )
Calculates redundant factors for xy->uv to speed drawing.
firstpoints ( -- )
Get the initial points for a map, interactive.
solve3x3 ( -- f. d. c. e. b. a. )
Solve for a map, calculated values on stack. Call either firstpoints
and imagepoints or initial and image before calling solve3x3.